using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Terra.Data.Context;
using Terra.Data.Entities.Identity;
using Terra.Data.Models.Identity;

namespace Terra.Data.Repository.Identity;

/// <summary>
/// 角色仓储实现
/// </summary>
public class RoleRepository : RepositoryBase<Role, Guid>, IRoleRepository
{
    private readonly TerraDbContext _terraDbContext;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="context">数据库上下文</param>
    public RoleRepository(TerraDbContext context) : base(context)
    {
        _terraDbContext = context;
    }

    /// <summary>
    /// 根据角色名查找角色
    /// </summary>
    /// <param name="roleName">角色名</param>
    /// <returns>角色实体</returns>
    public async Task<Role> FindByNameAsync(string roleName)
    {
        return await _dbContext.Set<Role>()
            .FirstOrDefaultAsync(x => x.NormalizedName == roleName.ToUpper());
    }

    /// <summary>
    /// 获取角色的用户列表
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <returns>用户列表</returns>
    public async Task<IList<User>> GetUsersInRoleAsync(Guid roleId)
    {
        return await _dbContext.Set<User>()
            .Where(u => u.UserRoles.Any(ur => ur.RoleId == roleId))
            .ToListAsync();
    }

    /// <summary>
    /// 获取系统角色列表
    /// </summary>
    /// <returns>系统角色列表</returns>
    public async Task<IList<Role>> GetSystemRolesAsync()
    {
        return await _dbContext.Set<Role>()
            .Where(r => r.IsSystem)
            .ToListAsync();
    }

    /// <summary>
    /// 分页查询角色列表
    /// </summary>
    /// <param name="query">查询条件</param>
    /// <returns>角色列表和总数</returns>
    public async Task<(List<Role> Items, int TotalCount)> GetPagedRolesAsync(RoleQueryDto query)
    {
        var queryable = _dbContext.Set<Role>().AsQueryable();

        // 按名称筛选
        if (!string.IsNullOrWhiteSpace(query.Name))
        {
            queryable = queryable.Where(r => r.Name.Contains(query.Name));
        }

        // 按系统角色筛选
        if (query.IsSystem.HasValue)
        {
            queryable = queryable.Where(r => r.IsSystem == query.IsSystem.Value);
        }

        // 获取总数
        var totalCount = await queryable.CountAsync();

        // 分页查询
        var items = await queryable
            .OrderByDescending(r => r.CreatedTime)
            .Skip((query.PageIndex - 1) * query.PageSize)
            .Take(query.PageSize)
            .ToListAsync();

        return (items, totalCount);
    }

    /// <summary>
    /// 检查角色名是否已存在
    /// </summary>
    /// <param name="roleName">角色名</param>
    /// <param name="excludeRoleId">排除的角色ID</param>
    /// <returns>是否存在</returns>
    public async Task<bool> ExistsByNameAsync(string roleName, Guid? excludeRoleId = null)
    {
        var query = _dbContext.Set<Role>()
            .Where(r => r.NormalizedName == roleName.ToUpper());

        if (excludeRoleId.HasValue && excludeRoleId.Value != Guid.Empty)
        {
            query = query.Where(r => r.Id != excludeRoleId.Value);
        }

        return await query.AnyAsync();
    }

    /// <summary>
    /// 批量删除角色
    /// </summary>
    /// <param name="roleIds">角色ID列表</param>
    /// <returns>删除结果</returns>
    public async Task<(bool Succeeded, List<Guid> FailedIds)> DeleteRolesAsync(IEnumerable<Guid> roleIds)
    {
        var roles = await _dbContext.Set<Role>()
            .Where(r => roleIds.Contains(r.Id))
            .ToListAsync();

        var failedIds = new List<Guid>();
        var deletedRoles = new List<Role>();

        foreach (var role in roles)
        {
            // 获取用户角色关系
            var userRoles = await _dbContext.Set<UserRole>()
                .Where(ur => ur.RoleId == role.Id)
                .ToListAsync();

            _dbContext.Set<UserRole>().RemoveRange(userRoles);
            _dbContext.Set<Role>().Remove(role);
        }

        await _dbContext.SaveChangesAsync();

        // 返回所有被请求删除但未在数据库中被删除的ID
        var deletedRoleIds = roles.Select(r => r.Id).ToList();
        failedIds = roleIds.Except(deletedRoleIds).ToList();

        return (failedIds.Count == 0, failedIds);
    }

    /// <summary>
    /// 为角色指定用户
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="userIds">用户ID列表</param>
    /// <returns>是否成功</returns>
    public async Task<bool> AssignUsersToRoleAsync(Guid roleId, IEnumerable<Guid> userIds)
    {
        try
        {
            // 查找现有的用户角色关系
            var existingUserRoles = await _dbContext.Set<UserRole>()
                .Where(ur => ur.RoleId == roleId)
                .ToListAsync();

            // 获取需要添加的用户ID
            var existingUserIds = existingUserRoles.Select(ur => ur.UserId).ToList();
            var newUserIds = userIds.Except(existingUserIds).ToList();

            // 添加新的用户角色关系
            foreach (var userId in newUserIds)
            {
                await _dbContext.Set<UserRole>().AddAsync(new UserRole
                {
                    Id = Guid.NewGuid(),
                    RoleId = roleId,
                    UserId = userId
                });
            }

            await _dbContext.SaveChangesAsync();
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    /// <summary>
    /// 从角色中移除用户
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="userIds">用户ID列表</param>
    /// <returns>是否成功</returns>
    public async Task<bool> RemoveUsersFromRoleAsync(Guid roleId, IEnumerable<Guid> userIds)
    {
        try
        {
            // 查找要删除的用户角色关系
            var userRolesToRemove = await _dbContext.Set<UserRole>()
                .Where(ur => ur.RoleId == roleId && userIds.Contains(ur.UserId))
                .ToListAsync();

            if (userRolesToRemove.Any())
            {
                _dbContext.Set<UserRole>().RemoveRange(userRolesToRemove);
                await _dbContext.SaveChangesAsync();
            }

            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    /// <summary>
    /// 获取角色选择列表
    /// </summary>
    /// <returns>角色选择列表</returns>
    public async Task<List<RoleSelectDto>> GetRoleSelectListAsync()
    {
        return await _dbContext.Set<Role>()
            .OrderBy(r => r.Name)
            .Select(r => new RoleSelectDto
            {
                Id = r.Id,
                Name = r.Name
            })
            .ToListAsync();
    }

    public async Task<List<Guid>> GetRolePermissionIdsAsync(Guid roleId)
    {
        return await _terraDbContext.Set<RolePermission>()
            .Where(rp => rp.RoleId == roleId)
            .Select(rp => rp.PermissionId)
            .ToListAsync();
    }

    public async Task SaveRolePermissionsAsync(Guid roleId, List<Guid> permissionIds)
    {
        // 获取现有的权限关联
        var existingPermissions = await _terraDbContext.Set<RolePermission>()
            .Where(rp => rp.RoleId == roleId)
            .ToListAsync();

        // 需要删除的权限关联
        var permissionsToDelete = existingPermissions
            .Where(rp => !permissionIds.Contains(rp.PermissionId))
            .ToList();

        // 需要添加的权限ID
        var permissionsToAdd = permissionIds
            .Except(existingPermissions.Select(rp => rp.PermissionId))
            .Select(permissionId => new RolePermission
            {
                Id = Guid.NewGuid(),
                RoleId = roleId,
                PermissionId = permissionId
            })
            .ToList();

        // 执行删除和添加操作
        if (permissionsToDelete.Any())
        {
            _terraDbContext.Set<RolePermission>().RemoveRange(permissionsToDelete);
        }

        if (permissionsToAdd.Any())
        {
            await _terraDbContext.Set<RolePermission>().AddRangeAsync(permissionsToAdd);
        }
    }

    public async Task DeleteRolePermissionsAsync(Guid roleId)
    {
        var permissions = await _terraDbContext.Set<RolePermission>()
            .Where(rp => rp.RoleId == roleId)
            .ToListAsync();

        if (permissions.Any())
        {
            _terraDbContext.Set<RolePermission>().RemoveRange(permissions);
        }
    }
}